<script lang="ts">
import {
  defineComponent,
  ref,
  onMounted,
  computed,
  reactive,
  getCurrentInstance,
  ComponentInternalInstance,
} from "vue";
interface Box {
  id: string;
  x1: number;
  x2: number;
  y1: number;
  y2: number;
  dom: string;
}
export default defineComponent({
  name: "origin",
  setup() {
    const instance = getCurrentInstance() as ComponentInternalInstance;
    const allOrigin = instance.appContext.config.globalProperties.$ORIGINS;
    console.log(allOrigin);
    /** $ref 获取 dom元素目标 */
    const origins = ref<HTMLElement | null>(null);
    /** 设置每一小格的间距 5px */
    const onesM = ref(8);
    /** 设置 布局格数 */
    const originN = 12;
    /** 每一小格的 宽度 和 高度 */
    const onesW = ref(0);
    /** 计算获取每一小格的 宽度 和 高度*/
    const getw = () => {
      if (origins.value) {
        console.dir(origins.value);
        const CW = origins.value.clientWidth - (originN - 1) * onesM.value;
        onesW.value = Math.floor((CW / originN) * 10) / 10;
      }
    };
    const datas = reactive<Box[]>([
      {
        id: "1",
        x1: 2,
        x2: 3,
        y1: 2,
        y2: 4,
        dom: allOrigin[0],
      },
      {
        id: "2",
        x1: 1,
        x2: 2,
        y1: 1,
        y2: 3,
        dom: allOrigin[1],
      },
      {
        id: "3",
        x1: 3,
        x2: 5,
        y1: 6,
        y2: 9,
        dom: allOrigin[1],
      },
    ]);
    onMounted(() => {
      getw();
      window.onresize = () => {
        getw();
      };
    });

    const gridR = computed(() => {
      return "repeat(4,1fr)";
    });

    /** 计算属性 计算高宽 */
    const calcH = computed(() => {
      return (num: number) => {
        return `${onesW.value * num + onesM.value * (num - 1)}px`;
      };
    });
    /** 计算属性 计算高宽 */
    const calcW = computed(() => {
      return (num: number) => {
        return `${onesW.value * num + onesM.value * (num - 1)}px`;
      };
    });

    const calsBox = computed(() => {
      return (vel: Box) => {
        return vel.id === thisbox.value
          ? {
              "grid-row": `${vel.x1}/${vel.x2}`,
              "grid-column": `${vel.y1}/${vel.y2}`,
              top: `${startInfo.top}px`,
              left: `${startInfo.left}px`,
              "z-index": 1,
            }
          : {
              "grid-row": `${vel.x1}/${vel.x2}`,
              "grid-column": `${vel.y1}/${vel.y2}`,
            };
      };
    });
    const boxclass = computed(() => {
      return (vel: Box) => {
        return `origin-box div1 ${vel.id === thisbox.value ? "act" : ""}`;
      };
    });
    /** 当前选中box */
    const thisbox = ref("");
    const startInfo = reactive({
      x: 0,
      y: 0,
      top: 0,
      left: 0,
    });

    /** 是否移动 */
    let moving = false;
    /** 鼠标移动 */
    const onMousedown = (event: MouseEvent, box: Box) => {
      event.preventDefault();
      thisbox.value = box.id;
      // console.log(event);
      startInfo.x = event.clientX;
      startInfo.y = event.clientY;
      toggleMoving(true);
    };
    /** 移动总事件 */
    const toggleMoving = (movable: boolean) => {
      if (movable) {
        document.addEventListener("mousemove", onMouseMove);
        document.addEventListener("mouseup", onMouseUp);
      } else {
        document.removeEventListener("mousemove", onMouseMove);
        document.removeEventListener("mouseup", onMouseUp);
      }
    };
    /** 移动事件 */
    const onMouseMove = (event: MouseEvent) => {
      event.preventDefault();
      moving = true;
      startInfo.top = event.clientY - startInfo.y;
      startInfo.left = event.clientX - startInfo.x;
    };
    /** 鼠标抬起事件 */
    const onMouseUp = (event: MouseEvent) => {
      event.preventDefault();
      if (moving) {
        moveNum();
        moving = false;
        startInfo.top = 0;
        startInfo.left = 0;
      }
      thisbox.value = "";
      toggleMoving(false);
    };
    /** 计算偏移量 */
    const moveNum = () => {
      const y = Number(
        (startInfo.left / (onesW.value + onesM.value)).toFixed()
      );
      const x = Number((startInfo.top / (onesW.value + onesM.value)).toFixed());
      const box = datas.filter((t) => t.id === thisbox.value)[0];
      const x1 = box.x1 + x;
      const x2 = box.x2 + x;
      const y1 = box.y1 + y;
      const y2 = box.y2 + y;
      if (
        x1 < 1 ||
        x1 > originN + 1 ||
        x2 < 1 ||
        x2 > originN + 1 ||
        y1 < 1 ||
        y1 > originN + 1 ||
        y2 < 1 ||
        y2 > originN + 1
      ) {
        return;
      }
      box.x1 = x1;
      box.x2 = x2;
      box.y1 = y1;
      box.y2 = y2;
    };
    return {
      origins,
      onesW,
      onesM,
      originN,
      calcH,
      calcW,
      datas,
      // gridR,
      calsBox,
      boxclass,
      thisbox,
      onMousedown,
    };
  },
});
</script>
<template>
  <div class="origin" ref="origins">
    <div class="totols"><el-button>编辑</el-button></div>
    <div
      class="origin-grid"
      :style="{
        height: `${onesW * originN + onesM * (originN - 1)}px`,
        'grid-template-rows': `repeat(${originN},1fr)`,
        'grid-template-columns': `repeat(${originN},1fr)`,
        'grid-gap': `${onesM}px`,
      }"
    >
      <template v-for="(t, i) in datas" :key="i">
        <div
          :class="boxclass(t)"
          :style="calsBox(t)"
          @mousedown="(e) => onMousedown(e, t)"
        >
          <component :is="t.dom"></component>
          {{ thisbox }}
        </div>
      </template>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.origin {
  position: relative;
  .totols {
    margin-bottom: 15px;
  }
  .origin-grid {
    display: grid;
  }
  .origin-box {
    position: relative;
    border-radius: 7px;
    overflow: hidden;
    cursor: pointer;
  }
  .act {
    box-shadow: 0 15px 30px rgb(0 0 0 / 10%);
  }
  .div1 {
    background-color: rgb(194, 194, 194);
  }
}
</style>
